﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using CADs;
using System.ComponentModel;
using ModeloGaleriaNET;
using System.Data.Objects.DataClasses;
using System.IO;
using System.Data;
using AvalonDock;
using SeguridadGaleria;

namespace GaleriaNET
{
    /// <summary>
    /// Lógica de interacción para ucAdmin.xaml
    /// </summary>
    public partial class ucAdmin : UserControl
    {
        #region Variables y atributos de la clase
        private string[] permisos = new string[] {TiposRoles.CREAR_USUARIO, TiposRoles.MODIFICAR_DATOS_USUARIO_PROPIO, TiposRoles.MODIFICAR_DATOS_OTRO_USUARIO,
        TiposRoles.VISUALIZAR_USUARIO, TiposRoles.ELIMINAR_USUARIO, TiposRoles.CAMBIAR_CONTRASENYA_USUARIO};
        private bool success;
        /// <summary>
        /// Indica si el formulario ha sido cargado al menos una vez
        /// </summary>
        private bool loaded;
        /// <summary>
        /// Título del control de usuario que se muestra fuera
        /// </summary>
        private readonly string title = "Administración de usuarios";
        /// <summary>
        /// Listado de usuarios de la página actual
        /// </summary>
        private List<Usuario> usuarios; 
        /// <summary>
        /// BackgroundWorker. Se usa para trabajar con la base de datos
        /// </summary>
        private BackgroundWorker worker, workerPermisos;
        /// <summary>
        /// Número de página actual de la búsqueda
        /// </summary>
        private int pagenum;
        /// <summary>
        /// Número de usuarios existentes en la galería
        /// </summary>
        private int numUsuarios;
        /// <summary>
        /// Número de elementos por página, definido en las propiedades del proyecto
        /// </summary>
        private readonly int pageSize = int.Parse(CADs.Properties.Resources.PageSize);
        /// <summary>
        /// CAD de Usuarios en la base de datos
        /// </summary>
        private UsuarioCAD usuarioCAD;

        private Dictionary<string, bool> permisosDatos;
        #endregion

        public ucAdmin()
        {
            InitializeComponent();

            #region Definición del BackgroundWorker
            worker = new BackgroundWorker();
            worker.DoWork += worker_DoWork;
            worker.RunWorkerCompleted += worker_RunWorkerCompleted;
            workerPermisos = new BackgroundWorker();
            workerPermisos.DoWork += workerPermisos_DoWork;
            workerPermisos.RunWorkerCompleted += workerPermisos_RunWorkerCompleted;
            #endregion

            #region Definición de columnas de botones en DataGrid
            dgUsuarios.Columns.Add(FindResource("resColumnaCliente") as DataGridTemplateColumn);
            dgUsuarios.Columns.Add(FindResource("resColumnaObra") as DataGridTemplateColumn);
            #endregion

            loaded = false;
        }

        public void AddEventHandler()
        {
            ((DocumentContent)this.Parent).Closing += ClosingDocument;
        }

        public string Title
        {
            get { return title; }
        }

        private void workerPermisos_DoWork(object sender, DoWorkEventArgs e)
        {
            bool? value;
            string usu;

            usu = Convert.ToString(Utilities.FindUsuarioData(GetContainerWindow().GetType(), this, "Name"));
            permisosDatos = new Dictionary<string, bool>();
            foreach (string s in permisos)
            {
                value = ManejadorRoles.Instance.CanUse(s, usu);
                if (value != null)
                    permisosDatos.Add(s, value.Value);
            }
        }

        private void workerPermisos_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            IntPtr b;
            BitmapSource bs;
            bool value;

            if (!(permisosDatos != null && permisosDatos.Count == permisos.Length))
            {
                Xceed.Wpf.Toolkit.MessageBox.Show("No se han podido obtener los permisos", "Error",
                    MessageBoxButton.OK, MessageBoxImage.Error);
                dgUsuarios.MouseDoubleClick -= dgUsuarios_MouseDoubleClick;
                b = Properties.Resources.Agregar_gris_24.GetHbitmap();
                bs = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(b, IntPtr.Zero, Int32Rect.Empty,
                  System.Windows.Media.Imaging.BitmapSizeOptions.FromEmptyOptions());
                this.imgBtNuevo.Source = bs;
                btNuevo.IsEnabled = false;
            }
            else
            {
                permisosDatos.TryGetValue(TiposRoles.VISUALIZAR_USUARIO, out value);
                if (!value)
                {
                    dgUsuarios.MouseDoubleClick -= dgUsuarios_MouseDoubleClick;
                    b = Properties.Resources.Agregar_gris_24.GetHbitmap();
                    bs = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(b, IntPtr.Zero, Int32Rect.Empty,
                      System.Windows.Media.Imaging.BitmapSizeOptions.FromEmptyOptions());
                    this.imgBtNuevo.Source = bs;
                    btNuevo.IsEnabled = false;
                }
                else
                {
                    // Modificar usuarios
                    permisosDatos.TryGetValue(TiposRoles.MODIFICAR_DATOS_OTRO_USUARIO, out value);
                    if (!value)
                        dgUsuarios.MouseDoubleClick -= dgUsuarios_MouseDoubleClick;

                    // Crear usuario
                    permisosDatos.TryGetValue(TiposRoles.CREAR_USUARIO, out value);
                    if (value)
                    {
                        b = Properties.Resources.Agregar_24.GetHbitmap();
                        bs = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(b, IntPtr.Zero, Int32Rect.Empty,
                          System.Windows.Media.Imaging.BitmapSizeOptions.FromEmptyOptions());
                        this.imgBtNuevo.Source = bs;
                        btNuevo.IsEnabled = true;
                    }
                    else
                    {
                        b = Properties.Resources.Agregar_gris_24.GetHbitmap();
                        bs = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(b, IntPtr.Zero, Int32Rect.Empty,
                          System.Windows.Media.Imaging.BitmapSizeOptions.FromEmptyOptions());
                        this.imgBtNuevo.Source = bs;
                        btNuevo.IsEnabled = false;
                    }
                }
            }
        }

        private void worker_DoWork(object sender, DoWorkEventArgs e)
        {
            try
            {
                usuarios = usuarioCAD.GetUsuariosPaginated(pagenum);
                numUsuarios = usuarioCAD.GetUsuariosCount();
                success = true;
            }
            catch (Exception)
            {
                success = false;
            }
        }

        private void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            _busyIndicator.IsBusy = false;
            if (success)
            {
                dgUsuarios.ItemsSource = usuarios;
                tbPaginacion.Visibility = Visibility.Visible;
                UpdatePaginationControls();
            }
            else
            {
                dgUsuarios.ItemsSource = null;
                Xceed.Wpf.Toolkit.MessageBox.Show("No se ha podido realizar la búsqueda",
                    "Error", MessageBoxButton.OK, MessageBoxImage.Error);
            }
        }

        private void UserControl_Loaded(object sender, RoutedEventArgs e)
        {
            if (!loaded)
            {
                if (!worker.IsBusy)
                {
                    _busyIndicator.IsBusy = true;
                    //usuarioCAD = GetContainerWindow().Usuario is Administrador ? new AdministradorCAD() : new UsuarioCAD();
                    usuarioCAD = new UsuarioCAD();
                    usuarioCAD.SetQueryFilters(null);
                    numUsuarios = -1;
                    pagenum = 0;
                    worker.RunWorkerAsync();
                    workerPermisos.RunWorkerAsync();
                }
                loaded = true;
            }
        }

        private void UpdatePaginationControls()
        {
            String iniString = "0";
            String deString = "";

            if (numUsuarios > 0)
                iniString = (pagenum * pageSize + 1).ToString();

            btAnterior.IsEnabled = pagenum == 0 ? false : true;

            if (pagenum + 1 >= numUsuarios / (float)pageSize)
            {
                btSiguiente.IsEnabled = false;
                deString = numUsuarios.ToString();
            }
            else
            {
                btSiguiente.IsEnabled = true;
                deString = ((pagenum + 1) * pageSize).ToString();
            }

            lbPagina.Content = iniString + " - " + deString + " de " + numUsuarios;
        }

        private void btAnterior_Click(object sender, RoutedEventArgs e)
        {
            if (!worker.IsBusy)
            {
                _busyIndicator.IsBusy = true;
                pagenum--;
                worker.RunWorkerAsync();
            }
        }

        private void btSiguiente_Click(object sender, RoutedEventArgs e)
        {
            if (!worker.IsBusy)
            {
                _busyIndicator.IsBusy = true;
                pagenum++;
                worker.RunWorkerAsync();
            }
        }

        private void btSiguiente_IsEnabledChanged(object sender, DependencyPropertyChangedEventArgs e)
        {
            IntPtr b;
            BitmapSource bs;

            if (imgBtSiguiente != null)
            {
                b = Convert.ToBoolean(e.NewValue) ? Properties.Resources.Right_24.GetHbitmap() : Properties.Resources.RightBW_24.GetHbitmap();
                bs = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(b, IntPtr.Zero, Int32Rect.Empty,
                  System.Windows.Media.Imaging.BitmapSizeOptions.FromEmptyOptions());
                this.imgBtSiguiente.Source = bs;
            }
        }

        private void btAnterior_IsEnabledChanged(object sender, DependencyPropertyChangedEventArgs e)
        {
            IntPtr b;
            BitmapSource bs;

            if (imgBtAnterior != null)
            {
                b = Convert.ToBoolean(e.NewValue) ? Properties.Resources.Left_24.GetHbitmap() : Properties.Resources.LeftBW_24.GetHbitmap();
                bs = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(b, IntPtr.Zero, Int32Rect.Empty,
                  System.Windows.Media.Imaging.BitmapSizeOptions.FromEmptyOptions());
                this.imgBtAnterior.Source = bs;
            }
        }

        private void dgUsuarios_MouseDoubleClick(object sender, MouseButtonEventArgs e)
        {
            DataGrid grid;
            DataGridRow dgr;
            DocumentContent doc;

            if (sender != null)
            {
                grid = sender as DataGrid;
                if (grid != null && grid.SelectedItems != null && grid.SelectedItems.Count == 1)
                {
                    dgr = grid.ItemContainerGenerator.ContainerFromItem(grid.SelectedItem) as DataGridRow;

                    if (dgr.Item is Administrador)
                    {
                        // Modificar datos de ti mismo
                        if (GetContainerWindow().Usuario.Id == ((Administrador)(dgr.Item)).Id)
                            GetContainerWindow().miUsuario_Click(this, null);
                        else // Modificar datos de otro usuario
                        {
                            doc = FindDocumentContent(typeof(ucUserData));

                            if (doc == null)
                                ShowPageInParentDock<ucUserData>((EntityObject)dgr.Item);
                            else
                                Xceed.Wpf.Toolkit.MessageBox.Show("Ya hay abierta una ventana de creación o edición de usuarios. Ciérrela antes de abrir otra.", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
                        }
                    }
                    else
                    {
                        if (dgr.Item is EntityObject)
                        {
                            doc = FindDocumentContent(typeof(ucUserData));

                            if (doc == null)
                                ShowPageInParentDock<ucUserData>(((EntityObject)dgr.Item));
                            else
                                Xceed.Wpf.Toolkit.MessageBox.Show("Ya hay abierta una ventana de creación o edición de usuarios. Ciérrela antes de abrir otra.", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
                        }
                    }
                }
            }
        }

        private void ShowPageInParentDock<T>(EntityObject obj = null) where T : UserControl
        {
            DependencyObject padre = this.Parent;
            ucUserData control;

            control = obj != null ? new ucUserData((Usuario)obj) : new ucUserData();
            control.UsuarioCAD = usuarioCAD;
            OpenNewDocument(control);
        }

        private void btNuevo_Click(object sender, RoutedEventArgs e)
        {
            DocumentContent doc = FindDocumentContent(typeof(ucUserData));

            if (doc == null)
                ShowPageInParentDock<ucUserData>();
            else
                Xceed.Wpf.Toolkit.MessageBox.Show("Ya hay abierta una ventana de creación o edición de usuarios. Ciérrela antes de abrir otra.",
                    "Error", MessageBoxButton.OK, MessageBoxImage.Error);
        }

        private void ClosingDocument(object sender, CancelEventArgs e)
        {
            DocumentContent doc = FindDocumentContent(typeof(ucUserData));

            if (doc != null)
            {
                if (Xceed.Wpf.Toolkit.MessageBox.Show("Hay abierta una ventana de creación o edición de usuarios. ¿Desea salir?",
                    "Cerrar ventana", MessageBoxButton.YesNo, MessageBoxImage.Question) == MessageBoxResult.No)
                    e.Cancel = true;
                else
                    doc.Close();
            }
        }

        private DocumentContent FindDocumentContent(Type t)
        {
            AvalonDock.DockingManager manager;

            manager = ((AvalonDock.DocumentContent)this.Parent).Manager;
            // Buscamos si hay abierta una instancia del documento a abrir
            foreach (AvalonDock.DocumentContent doc in manager.Documents)
            {
                if (doc.Content.GetType() == t)
                    return doc;
            }
            return null;
        }

        public void ActualizarDataGrid()
        {
            if (!worker.IsBusy)
            {
                _busyIndicator.IsBusy = true;
                usuarioCAD = new UsuarioCAD();
               // usuarioCAD = GetContainerWindow().Usuario is Administrador ? new AdministradorCAD() : new UsuarioCAD();
                usuarioCAD.SetQueryFilters(null);
                dgUsuarios.ItemsSource = null;
                numUsuarios = -1;
                worker.RunWorkerAsync();
            }
        }

        private UserWindow GetContainerWindow()
        {
            DockingManager manager;
            manager = ((DocumentContent)(this.Parent)).Manager;
            return (UserWindow)(((Grid)(manager.Parent)).Parent);
        }

        private void btBuscar_Click(object sender, RoutedEventArgs e)
        {
            UserFilterWindow busqueda;
            
            busqueda = new UserFilterWindow();
            busqueda.ShowDialog();

            if (busqueda.Success) // Realizar búsqueda
            {
                if (!worker.IsBusy)
                {
                    _busyIndicator.IsBusy = true;
                    usuarioCAD.SetQueryFilters(busqueda.Filters);
                    dgUsuarios.ItemsSource = null;
                    dgUsuarios.Items.Clear();
                    numUsuarios = -1;
                    pagenum = 0;
                    worker.RunWorkerAsync();
                }
            }
        }

        private void btLimpiar_Click(object sender, RoutedEventArgs e)
        {
            _busyIndicator.IsBusy = true;
            usuarioCAD.SetQueryFilters(null);
            numUsuarios = -1;
            pagenum = 0;
            worker.RunWorkerAsync();
        }

        private void Button_Obras_Click(object sender, RoutedEventArgs e)
        {
            DocumentContent doc;
            ucObras control;
            DataGridRow dgr;

            if (sender != null)
            {
                if (dgUsuarios.SelectedItems != null && dgUsuarios.SelectedItems.Count == 1)
                {
                    doc = FindDocumentContent(typeof(ucObras));
                    if (doc != null)
                        Xceed.Wpf.Toolkit.MessageBox.Show("Hay abierta una ventana de listado de obras.\nCiérrela antes de abrir otra",
                            "Error", MessageBoxButton.OK, MessageBoxImage.Error);
                    else
                    {
                        dgr = dgUsuarios.ItemContainerGenerator.ContainerFromItem(dgUsuarios.SelectedItem) as DataGridRow;
                        control = new ucObras(((Usuario)dgr.Item).Id);
                        OpenNewDocument(control);
                   
                    }
                }
            }
        }

        private void OpenNewDocument(UserControl c)
        {
            DependencyObject padre;

            try
            {
                padre = this.Parent;
                if (padre is AvalonDock.DocumentContent)
                {
                    padre = ((AvalonDock.DocumentContent)padre).Manager;
                    if (padre is AvalonDock.DockingManager)
                    {
                        padre = ((AvalonDock.DockingManager)padre).Parent;
                        if (padre is Grid)
                        {
                            padre = ((Grid)padre).Parent;

                            if (padre is UserWindow)
                            {
                                if (c is ucObras)
                                    ((UserWindow)padre).ShowPage<ucObras>((ucObras)c);
                                else if (c is ucUserData)
                                    ((UserWindow)padre).ShowPage<ucUserData>((ucUserData)c);
                                else if (c is ucClientes)
                                    ((UserWindow)padre).ShowPage<ucClientes>((ucClientes)c);
                            }
                            else
                                throw new ErrorOpeningNewDocumentException("No se puede abrir la nueva ventana");
                        }
                        else
                            throw new ErrorOpeningNewDocumentException("No se puede abrir la nueva ventana");
                    }
                    else
                        throw new ErrorOpeningNewDocumentException("No se puede abrir la nueva ventana");
                }
                else
                    throw new ErrorOpeningNewDocumentException("No se puede abrir la nueva ventana");
            }
            catch (ErrorOpeningNewDocumentException ex)
            {
                Xceed.Wpf.Toolkit.MessageBox.Show(ex.Message, "Error", MessageBoxButton.OK, MessageBoxImage.Error);
                return;
            }
        }

        private void Button_Clientes_Click(object sender, RoutedEventArgs e)
        {
            DocumentContent doc;
            ucClientes control;
            DataGridRow dgr;

            if (sender != null)
            {
                if (dgUsuarios.SelectedItems != null && dgUsuarios.SelectedItems.Count == 1)
                {
                    doc = FindDocumentContent(typeof(ucClientes));
                    if (doc != null)
                        Xceed.Wpf.Toolkit.MessageBox.Show("Hay abierta una ventana de listado de clientes.\nCiérrela antes de abrir otra",
                            "Error", MessageBoxButton.OK, MessageBoxImage.Error);
                    else
                    {
                        dgr = dgUsuarios.ItemContainerGenerator.ContainerFromItem(dgUsuarios.SelectedItem) as DataGridRow;
                        control = new ucClientes(((Usuario)dgr.Item).Id);
                        OpenNewDocument(control);

                    }
                }
            }
        }
    }
}
